package com.webull.information.center.carwler.common.util;

import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedInput;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.util.Optional;
import java.util.function.Consumer;

@Component
public class HttpClientUtil {
    protected final Logger logger = LogManager.getLogger(getClass());

    private @Autowired
    CarwlerNetWorksUtil networksIPUtil;


    public SyndFeed retriveRssSyndFeed(String rss, Boolean proxy) {
        long startTime = System.currentTimeMillis();
        try {
            String contxt = getStringEntity(rss, proxy);
            if (StringUtils.isNotBlank(contxt))
                return new SyndFeedInput().build(new StringReader(contxt));
            logger.warn("retriveRssSyndFeed rss:{},contxt is {}", rss, contxt);
            return null;
        } catch (Exception e) {
            logger.error("HttpReaderUtil obtainSyndFeed:{},costTime:{},proxy:{}",
                    rss, (System.currentTimeMillis() - startTime), proxy, e);
            return null;
        }
    }


    public String getStringEntity(String url, Boolean proxy) {
        long startTime = System.currentTimeMillis();
        try {
            String[] res = {null};
            Consumer<HttpEntity> cons = entity -> {
                try {
                    res[0] = EntityUtils.toString(entity, "UTF-8");
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            };
            retriveHttpResponse(url, proxy, cons);
            return res[0];
        } catch (Exception e) {
            logger.error("HttpReaderUtil getStringEntity:{} ,costTime:{},proxy:{}",
                    url, (System.currentTimeMillis() - startTime), proxy, e);
        }
        return null;
    }

    public byte[] getByteEntity(String url, Boolean proxy) {
        long startTime = System.currentTimeMillis();
        try {
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            Consumer<HttpEntity> cons = entity -> {
                try {
                    IOUtils.copy(entity.getContent(), bo);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            };
            retriveHttpResponse(url, proxy, cons);
            return bo.toByteArray();
        } catch (Exception e) {
            logger.error("HttpReaderUtil getByteEntity:{} ,costTime:{},proxy:{}",
                    url, (System.currentTimeMillis() - startTime), proxy, e);
        }
        return null;
    }

    /**
     * <pre>
     * 暂不需要返回response更多元信息
     * 仅仅返回context的byte[]
     * </pre>
     *
     * @param url
     * @param proxy
     * @return
     * @throws Exception
     */
    private void retriveHttpResponse(String url, Boolean proxy, Consumer<HttpEntity> consumer) {
        long startTime = System.currentTimeMillis();
        CarwlerNetWorksUtil.ProxyService proxySer = null;
        try (CloseableHttpClient closeableHttpClient = HttpClientBuilder.create().build()) {
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout)
                    .setConnectTimeout(connectTimeout).build();
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0");
            httpGet.addHeader("x-client-data", RandomStringUtils.randomAlphanumeric(40));
            httpGet.addHeader("Cache-Control", "no-cache");
            httpGet.setConfig(requestConfig);
            HttpClientContext context = HttpClientContext.create();
            proxySer = networksIPUtil.smartProxyModel(proxy);
            Optional.ofNullable(proxySer)
                    .ifPresent(p -> context.setAttribute("socks.address", p.genSocketAddress()));

            try (CloseableHttpResponse httpResponse = closeableHttpClient.execute(httpGet, context);) {
                HttpEntity httpEntity = httpResponse.getEntity();
                int httpStatu = httpResponse.getStatusLine().getStatusCode();
                if (200 == httpStatu) {
                    consumer.accept(httpEntity);
                } else {
                    logger.warn("HttpReaderUtil retriveHttpResponse ,httpStatu:{},proxy:{},url:{}", httpStatu, proxy, url);
                }
            }
        } catch (Exception e) {
            logger.error("HttpReaderUtil getHttpContext error,url:{} ,costTime:{},proxy:{},proxySer:{}" + e.getMessage(), url, (System.currentTimeMillis() - startTime), proxy, proxySer);
        }
    }

    private static int socketTimeout = 20000;// 请求超时时间
    private static int connectTimeout = 20000;// 传输超时时间


}
